<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSON数据 → ECharts可视化工具（多Y轴+PNG下载）</title>
    <!-- 外部资源引入 -->
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jsonlint@1.6.3/web/jsonlint.min.js"></script>

    <!-- Tailwind配置 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#3b82f6',    // 主色调：蓝色
                        secondary: '#10b981',  // 辅助色：绿色
                        neutral: '#1f2937',    // 中性色：深灰
                        danger: '#ef4444',     // 错误色：红色
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>

    <!-- 自定义工具类 -->
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto { content-visibility: auto; }
            .card-shadow { box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
            .transition-all-300 { transition: all 0.3s ease; }
            .pulse-animation { animation: pulse 2s infinite; }
            .json-highlight { 
                color: #0550ae; 
                background-color: #f0f7ff;
                padding: 0.1rem 0.3rem;
                border-radius: 0.25rem;
            }
            .download-tooltip {
                position: relative;
            }
            .download-tooltip:hover::after {
                content: attr(data-tooltip);
                position: absolute;
                bottom: 100%;
                left: 50%;
                transform: translateX(-50%);
                background-color: #1f2937;
                color: white;
                padding: 4px 8px;
                border-radius: 4px;
                font-size: 12px;
                white-space: nowrap;
                z-index: 10;
                opacity: 0.9;
            }
            .download-progress {
                position: absolute;
                top: 0;
                left: 0;
                height: 100%;
                background-color: rgba(16, 185, 129, 0.2);
                border-radius: inherit;
                transition: width 0.3s ease;
                width: 0%;
                z-index: 0;
            }
        }
    </style>

    <style>
        /* 基础样式补充 */
        body { font-family: 'Inter', system-ui, sans-serif; }
        .upload-hover:hover { border-color: #3b82f6; background-color: #eff6ff; }
        .chart-container { height: 550px; width: 100%; }
        .json-editor { 
            font-family: 'Consolas', 'Monaco', monospace;
            font-size: 0.9rem;
            line-height: 1.6;
        }
        .error-details { max-height: 0; overflow: hidden; transition: max-height 0.5s ease; }
        .error-details.show { max-height: 400px; }
        .update-indicator {
            display: inline-block;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            margin-left: 6px;
            opacity: 0;
        }
        .updating .update-indicator {
            background-color: #3b82f6;
            animation: pulse 1.5s infinite;
            opacity: 1;
        }
        .series-item {
            transition: all 0.3s ease;
        }
        .series-item:hover {
            background-color: #f9fafb;
        }
        .axis-color-picker {
            width: 24px;
            height: 24px;
            border: 1px solid #ddd;
            cursor: pointer;
        }
        .download-btn-container {
            position: relative;
            overflow: hidden;
        }
        .download-btn {
            position: relative;
            z-index: 1;
        }
        /* JSON格式化样式 */
        .json-key { color: #953800; }
        .json-string { color: #0550ae; }
        .json-number { color: #0086b3; }
        .json-boolean { color: #d23737; }
        .json-null { color: #7d3c98; }
        @keyframes pulse {
            0% { transform: scale(0.95); opacity: 0.7; }
            50% { transform: scale(1.1); opacity: 1; }
            100% { transform: scale(0.95); opacity: 0.7; }
        }
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        .spinner {
            display: inline-block;
            width: 16px;
            height: 16px;
            border: 2px solid rgba(255,255,255,0.3);
            border-radius: 50%;
            border-top-color: white;
            animation: spin 1s ease-in-out infinite;
            margin-right: 6px;
        }
        .notification {
            position: fixed;
            bottom: 20px;
            right: 20px;
            padding: 12px 20px;
            background-color: #10b981;
            color: white;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            transform: translateY(100px);
            opacity: 0;
            transition: transform 0.3s ease, opacity 0.3s ease;
            z-index: 1000;
            display: flex;
            align-items: center;
        }
        .notification.show {
            transform: translateY(0);
            opacity: 1;
        }
        .notification.error {
            background-color: #ef4444;
        }
        .notification-icon {
            margin-right: 8px;
            font-size: 18px;
        }
    </style>
</head>
<body class="bg-gray-50 min-h-screen">
    <!-- 页面头部 -->
    <header class="bg-white shadow-sm sticky top-0 z-40">
        <div class="container mx-auto px-4 py-4 md:py-6">
            <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
                <div>
                    <h1 class="text-[clamp(1.4rem,3vw,1.8rem)] font-bold text-neutral flex items-center">
                        <i class="fa fa-file-code-o text-primary mr-3 text-2xl"></i>
                        JSON → ECharts 可视化工具
                    </h1>
                    <p class="text-gray-500 mt-1 text-sm md:text-base">多Y轴支持 · 实时更新 · 高清PNG下载</p>
                </div>
                <div class="flex items-center gap-2 text-sm text-gray-500">
                    <i class="fa fa-info-circle text-primary"></i>
                    <span>支持多数据系列与PNG图片导出</span>
                </div>
            </div>
        </div>
    </header>

    <!-- 通知提示组件 -->
    <div id="notification" class="notification">
        <i class="fa fa-check-circle notification-icon"></i>
        <span id="notification-message">操作成功！</span>
    </div>

    <!-- 主要内容区 -->
    <main class="container mx-auto px-4 py-6">
        <!-- 1. 数据导入区域 -->
        <section id="data-import" class="mb-8">
            <div class="bg-white rounded-xl p-5 md:p-6 card-shadow">
                <h2 class="text-lg md:text-xl font-semibold text-neutral mb-4 flex items-center">
                    <i class="fa fa-upload text-primary mr-2"></i>
                    步骤1：导入或输入JSON数据
                </h2>

                <!-- 导入方式切换 -->
                <div class="flex border-b border-gray-200 mb-4">
                    <button id="upload-tab" class="px-4 py-2 text-primary border-b-2 border-primary font-medium">
                        上传JSON文件
                    </button>
                    <button id="manual-tab" class="px-4 py-2 text-gray-500 hover:text-gray-700">
                        手动输入JSON
                    </button>
                </div>

                <!-- 上传区域 -->
                <div id="upload-area" class="mb-4">
                    <div id="upload-container" class="border-2 border-dashed border-gray-300 rounded-lg p-6 md:p-8 text-center upload-hover transition-all-300 cursor-pointer">
                        <i class="fa fa-file-text-o text-5xl text-gray-400 mb-4"></i>
                        <p class="text-gray-600 mb-2">拖放JSON文件到此处，或点击选择文件</p>
                        <p class="text-gray-400 text-sm mb-4">支持 .json 格式，建议文件大小不超过5MB</p>
                        <input type="file" id="file-input" accept=".json" class="hidden">
                        <button id="browse-btn" class="bg-primary hover:bg-primary/90 text-white px-6 py-2.5 rounded-lg transition-all-300 flex items-center justify-center mx-auto">
                            <i class="fa fa-folder-open mr-2"></i>选择JSON文件
                        </button>
                    </div>

                    <!-- 文件信息（上传后显示） -->
                    <div id="file-info" class="mt-4 hidden">
                        <div class="flex items-center justify-between bg-gray-50 p-3 rounded-lg">
                            <div class="flex items-center">
                                <i class="fa fa-check-circle text-secondary mr-2"></i>
                                <span id="file-name" class="font-medium text-gray-800"></span>
                                <span id="file-size" class="text-gray-500 text-sm ml-2"></span>
                            </div>
                            <button id="remove-file" class="text-red-500 hover:text-red-700 transition-all-300">
                                <i class="fa fa-times"></i> 移除
                            </button>
                        </div>
                    </div>
                </div>

                <!-- 手动输入区域（默认隐藏） -->
                <div id="manual-area" class="hidden">
                    <div class="mb-3">
                        <label class="block text-gray-700 mb-2 text-sm font-medium">
                            输入JSON数据（支持多字段对象数组）
                        </label>
                        <div class="bg-gray-50 p-3 rounded-lg text-sm mb-3">
                            <p class="font-medium mb-1">推荐格式（多字段对象数组）：</p>
                            <pre class="text-xs overflow-x-auto"><code>[
  { "month": "一月", "sales": 150, "visitors": 3200, "conversion": 4.69 },
  { "month": "二月", "sales": 230, "visitors": 4500, "conversion": 5.11 },
  ...
]</code></pre>
                        </div>
                        <textarea id="json-input" class="json-editor w-full h-48 p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all-300" placeholder='请输入JSON数据，例如：
[{ "month": "一月", "sales": 150, "visitors": 3200 },
 { "month": "二月", "sales": 230, "visitors": 4500 },
 { "month": "三月", "sales": 180, "visitors": 3800 }]'></textarea>
                    </div>
                    <button id="validate-json" class="bg-secondary hover:bg-secondary/90 text-white px-4 py-2 rounded-lg transition-all-300">
                        <i class="fa fa-check mr-1"></i>验证并加载数据
                    </button>
                </div>

                <!-- JSON解析错误提示区域 -->
                <div id="json-error" class="mt-4 hidden">
                    <div class="bg-red-50 border border-red-200 rounded-lg p-4">
                        <div class="flex items-start">
                            <i class="fa fa-exclamation-circle text-danger text-xl mt-0.5 mr-3"></i>
                            <div class="flex-1">
                                <h3 class="font-medium text-danger flex items-center">
                                    JSON解析失败
                                    <button id="show-error-details" class="ml-2 text-sm text-red-600 hover:underline">
                                        查看详情
                                    </button>
                                </h3>
                                <p id="error-message" class="text-red-600 text-sm mt-1">解析过程中发生错误</p>
                                
                                <!-- 错误详情 -->
                                <div id="error-details" class="error-details mt-3 text-sm bg-red-50 p-3 rounded border border-red-100 text-red-700 overflow-x-auto">
                                    <pre id="error-stack" class="whitespace-pre-wrap break-all text-xs"></pre>
                                </div>
                                
                                <!-- 解决方案建议 -->
                                <div class="mt-3 text-sm text-red-700">
                                    <p class="font-medium mb-1">请检查：</p>
                                    <ul class="list-disc pl-5 space-y-1">
                                        <li>JSON格式是否正确（使用逗号分隔，引号闭合）</li>
                                        <li>数据是否为对象数组格式，包含多个字段</li>
                                        <li>是否包含特殊字符或非法转义</li>
                                    </ul>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 数据预览区域（加载成功后显示） -->
                <div id="data-preview" class="mt-6 hidden">
                    <div class="bg-gray-50 p-4 rounded-lg">
                        <h3 class="font-medium text-gray-800 mb-3 flex items-center">
                            <i class="fa fa-table text-primary mr-2"></i>
                            数据预览（前10条）
                        </h3>
                        <div class="overflow-x-auto">
                            <table class="min-w-full divide-y divide-gray-200 bg-white rounded-lg">
                                <thead class="bg-gray-50">
                                    <tr id="preview-header"></tr>
                                </thead>
                                <tbody id="preview-body" class="bg-white divide-y divide-gray-200"></tbody>
                            </table>
                        </div>
                        <div class="mt-3 text-right">
                            <button id="go-to-config" class="bg-primary hover:bg-primary/90 text-white px-6 py-2.5 rounded-lg transition-all-300">
                                下一步：配置图表 <i class="fa fa-arrow-right ml-1"></i>
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- 2. 图表配置与展示区域 -->
        <section id="chart-section" class="mb-8 hidden">
            <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
                <!-- 配置面板 -->
                <div class="lg:col-span-1">
                    <div class="bg-white rounded-xl p-5 md:p-6 card-shadow h-full">
                        <h2 class="text-lg md:text-xl font-semibold text-neutral mb-4 flex items-center">
                            <i class="fa fa-sliders text-primary mr-2"></i>
                            图表配置
                        </h2>

                        <div class="space-y-4 mb-6">
                            <!-- 图表类型选择 -->
                            <div>
                                <label class="block text-gray-700 mb-2 text-sm font-medium">图表类型</label>
                                <select id="chart-type" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                    <option value="line">折线图</option>
                                    <option value="bar">柱状图</option>
                                    <option value="scatter">散点图</option>
                                    <option value="radar">雷达图</option>
                                    <option value="pie" disabled>饼图（不支持多Y轴）</option>
                                    <option value="doughnut" disabled>环形图（不支持多Y轴）</option>
                                    <option value="funnel" disabled>漏斗图（不支持多Y轴）</option>
                                </select>
                            </div>

                            <!-- X轴/类别字段选择 -->
                            <div id="x-axis-group">
                                <label class="block text-gray-700 mb-2 text-sm font-medium">X轴/类别字段</label>
                                <select id="x-axis-field" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                    <!-- 动态填充字段 -->
                                </select>
                            </div>

                            <!-- 多Y轴数据系列配置 -->
                            <div>
                                <div class="flex justify-between items-center mb-2">
                                    <label class="block text-gray-700 text-sm font-medium">数据系列（Y轴）</label>
                                    <button id="add-series" class="text-primary hover:text-primary/80 text-sm flex items-center">
                                        <i class="fa fa-plus-circle mr-1"></i> 添加系列
                                    </button>
                                </div>
                                
                                <div id="series-container" class="space-y-3">
                                    <!-- 数据系列项将动态添加到这里 -->
                                    <div class="series-item p-3 border border-gray-200 rounded-lg">
                                        <div class="flex justify-between items-start mb-2">
                                            <label class="text-sm font-medium text-gray-700">系列 1</label>
                                            <button type="button" class="remove-series text-gray-400 hover:text-danger" disabled>
                                                <i class="fa fa-trash"></i>
                                            </button>
                                        </div>
                                        <div class="grid grid-cols-1 gap-3">
                                            <div>
                                                <label class="block text-gray-600 mb-1 text-xs">数据字段</label>
                                                <select class="series-field w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                                    <!-- 动态填充字段 -->
                                                </select>
                                            </div>
                                            <div>
                                                <label class="block text-gray-600 mb-1 text-xs">系列名称</label>
                                                <input type="text" class="series-name w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300" placeholder="系列名称">
                                            </div>
                                            <div class="grid grid-cols-2 gap-2">
                                                <div>
                                                    <label class="block text-gray-600 mb-1 text-xs">图表类型</label>
                                                    <select class="series-type w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                                        <option value="line">折线图</option>
                                                        <option value="bar">柱状图</option>
                                                    </select>
                                                </div>
                                                <div>
                                                    <label class="block text-gray-600 mb-1 text-xs">线条/柱形颜色</label>
                                                    <input type="color" class="series-color w-full p-1 border border-gray-300 rounded-lg" value="#3b82f6">
                                                </div>
                                            </div>
                                            <div>
                                                <label class="flex items-center">
                                                    <input type="checkbox" class="series-y-axis mr-2 h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded" checked>
                                                    <span class="text-xs text-gray-600">使用独立Y轴</span>
                                                </label>
                                            </div>
                                            <div class="series-y-axis-config">
                                                <label class="block text-gray-600 mb-1 text-xs">Y轴标题</label>
                                                <input type="text" class="series-y-title w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300" placeholder="Y轴标题">
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                
                                <p class="text-xs text-gray-500 mt-2">
                                    <i class="fa fa-info-circle mr-1"></i> 最多支持5个数据系列，可分别配置图表类型和Y轴
                                </p>
                            </div>

                            <!-- 主题选择 -->
                            <div>
                                <label class="block text-gray-700 mb-2 text-sm font-medium">图表主题</label>
                                <select id="chart-theme" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                    <option value="light">浅色主题</option>
                                    <option value="dark">深色主题</option>
                                    <option value="vintage">复古主题</option>
                                    <option value="macarons">马卡龙主题</option>
                                    <option value="infographic">信息图主题</option>
                                    <option value="shine">明亮主题</option>
                                    <option value="roma">罗马主题</option>
                                </select>
                            </div>
                        </div>

                        <!-- 高级配置 -->
                        <div class="mb-6">
                            <button id="advanced-config-toggle" class="flex items-center text-primary hover:text-primary/80 text-sm font-medium">
                                <i class="fa fa-cog mr-1"></i> 高级配置（可选）
                                <i id="config-arrow" class="fa fa-angle-down ml-1 transition-transform-300"></i>
                            </button>
                            
                            <div id="advanced-config" class="mt-4 hidden bg-gray-50 p-4 rounded-lg space-y-4">
                                <!-- 图表标题 -->
                                <div>
                                    <label class="block text-gray-700 mb-2 text-sm font-medium">图表标题</label>
                                    <input type="text" id="chart-title" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all-300" placeholder="请输入图表标题">
                                </div>

                                <!-- 副标题 -->
                                <div>
                                    <label class="block text-gray-700 mb-2 text-sm font-medium">副标题</label>
                                    <input type="text" id="chart-subtitle" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all-300" placeholder="请输入副标题（可选）">
                                </div>

                                <!-- X轴标题 -->
                                <div>
                                    <label class="block text-gray-700 mb-2 text-sm font-medium">X轴标题</label>
                                    <input type="text" id="x-axis-title" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all-300" placeholder="请输入X轴标题">
                                </div>

                                <!-- 图例位置 -->
                                <div>
                                    <label class="block text-gray-700 mb-2 text-sm font-medium">图例位置</label>
                                    <select id="legend-position" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                        <option value="top">顶部</option>
                                        <option value="right">右侧</option>
                                        <option value="bottom">底部</option>
                                        <option value="left">左侧</option>
                                        <option value="none">不显示</option>
                                    </select>
                                </div>

                                <!-- 动画效果 -->
                                <div>
                                    <label class="block text-gray-700 mb-2 text-sm font-medium">动画效果</label>
                                    <select id="animation-type" class="w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                        <option value="auto">自动</option>
                                        <option value="none">无动画</option>
                                        <option value="slow">缓慢</option>
                                        <option value="fast">快速</option>
                                    </select>
                                </div>

                                <!-- 下载配置 -->
                                <div>
                                    <label class="block text-gray-700 mb-2 text-sm font-medium">PNG下载配置</label>
                                    <div class="grid grid-cols-2 gap-3">
                                        <div>
                                            <label class="block text-gray-600 mb-1 text-xs">图片质量</label>
                                            <select id="download-quality" class="w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                                <option value="0.8">标准 (0.8)</option>
                                                <option value="0.5">压缩 (0.5)</option>
                                                <option value="1.0" selected>高清 (1.0)</option>
                                            </select>
                                        </div>
                                        <div>
                                            <label class="block text-gray-600 mb-1 text-xs">像素比例</label>
                                            <select id="download-pixel-ratio" class="w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                                <option value="1">标准 (1x)</option>
                                                <option value="2" selected>高清 (2x)</option>
                                                <option value="3">超高清 (3x)</option>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div class="flex justify-between items-center">
                            <button id="back-to-import" class="border border-gray-300 text-gray-700 hover:bg-gray-50 px-4 py-2 rounded-lg transition-all-300">
                                <i class="fa fa-arrow-left mr-1"></i> 返回
                            </button>
                            <button id="apply-changes" class="bg-secondary hover:bg-secondary/90 text-white px-6 py-2.5 rounded-lg transition-all-300 flex items-center">
                                <span>应用更改</span>
                                <span class="update-indicator"></span>
                            </button>
                        </div>
                    </div>
                </div>

                <!-- 图表展示区域 -->
                <div class="lg:col-span-2">
                    <div class="bg-white rounded-xl p-5 md:p-6 card-shadow h-full flex flex-col">
                        <div class="flex flex-col md:flex-row md:items-center md:justify-between mb-6 gap-4">
                            <h2 class="text-lg md:text-xl font-semibold text-neutral flex items-center">
                                <i class="fa fa-line-chart text-primary mr-2"></i>
                                图表展示
                            </h2>
                            <div class="flex flex-wrap gap-3">
                                <div class="download-btn-container">
                                    <div class="download-progress" id="png-progress"></div>
                                    <button id="download-png" class="download-btn bg-gray-800 hover:bg-gray-900 text-white px-4 py-2 rounded-lg transition-all-300 flex items-center download-tooltip" data-tooltip="下载高清PNG图片">
                                        <i class="fa fa-download mr-2"></i>下载PNG
                                    </button>
                                </div>
                                <div class="download-btn-container">
                                    <div class="download-progress" id="svg-progress"></div>
                                    <button id="download-svg" class="download-btn bg-gray-800 hover:bg-gray-900 text-white px-4 py-2 rounded-lg transition-all-300 flex items-center download-tooltip" data-tooltip="下载矢量SVG图片">
                                        <i class="fa fa-download mr-2"></i>下载SVG
                                    </button>
                                </div>
                            </div>
                        </div>

                        <!-- 图表容器 -->
                        <div class="chart-container bg-gray-50 rounded-lg p-4 flex-grow">
                            <div id="echarts-container" class="w-full h-full"></div>
                        </div>

                        <!-- 图表数据说明 -->
                        <div class="mt-6 bg-gray-50 p-4 rounded-lg">
                            <h3 class="font-medium text-gray-800 mb-2 flex items-center">
                                <i class="fa fa-info-circle text-primary mr-2"></i>
                                图表数据说明
                            </h3>
                            <p class="text-gray-600 text-sm">
                                图表基于您提供的JSON数据生成，包含 <span id="data-count" class="font-medium text-primary"></span> 条记录和 <span id="series-count" class="font-medium text-primary">1</span> 个数据系列。
                                <span class="text-green-600">修改配置后图表将自动更新</span>
                            </p>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </main>

    <!-- 页脚 -->
    <footer class="bg-white border-t border-gray-200 py-6">
        <div class="container mx-auto px-4 text-center text-gray-500 text-sm">
            <p>JSON → ECharts 可视化工具 | 支持多Y轴数据展示与PNG下载</p>
            <p class="mt-1">所有数据处理均在本地完成，不会上传至服务器</p>
        </div>
    </footer>

    <!-- JavaScript 逻辑 -->
    <script>
        // 全局变量
        let jsonData = null;
        let chartInstance = null;
        let dataFields = []; // 数据字段列表
        let lastConfig = {}; // 存储上一次的配置，用于检测变化
        let updateTimeout = null; // 用于延迟更新的计时器
        const MAX_SERIES = 5; // 最大数据系列数量

        // 预设颜色列表，用于新添加的数据系列
        const presetColors = [
            '#3b82f6', // 蓝色
            '#10b981', // 绿色
            '#ef4444', // 红色
            '#f59e0b', // 橙色
            '#8b5cf6'  // 紫色
        ];

        // DOM 元素
        const uploadTab = document.getElementById('upload-tab');
        const manualTab = document.getElementById('manual-tab');
        const uploadArea = document.getElementById('upload-area');
        const manualArea = document.getElementById('manual-area');
        const fileInput = document.getElementById('file-input');
        const browseBtn = document.getElementById('browse-btn');
        const uploadContainer = document.getElementById('upload-container');
        const fileInfo = document.getElementById('file-info');
        const fileName = document.getElementById('file-name');
        const fileSize = document.getElementById('file-size');
        const removeFile = document.getElementById('remove-file');
        const jsonInput = document.getElementById('json-input');
        const validateJson = document.getElementById('validate-json');
        const jsonError = document.getElementById('json-error');
        const errorMessage = document.getElementById('error-message');
        const errorStack = document.getElementById('error-stack');
        const showErrorDetails = document.getElementById('show-error-details');
        const errorDetails = document.getElementById('error-details');
        const dataPreview = document.getElementById('data-preview');
        const previewHeader = document.getElementById('preview-header');
        const previewBody = document.getElementById('preview-body');
        const goToConfig = document.getElementById('go-to-config');
        const chartSection = document.getElementById('chart-section');
        const backToImport = document.getElementById('back-to-import');
        const xAxisField = document.getElementById('x-axis-field');
        const chartType = document.getElementById('chart-type');
        const chartTheme = document.getElementById('chart-theme');
        const advancedConfigToggle = document.getElementById('advanced-config-toggle');
        const advancedConfig = document.getElementById('advanced-config');
        const configArrow = document.getElementById('config-arrow');
        const applyChangesBtn = document.getElementById('apply-changes');
        const echartsContainer = document.getElementById('echarts-container');
        const downloadPng = document.getElementById('download-png');
        const downloadSvg = document.getElementById('download-svg');
        const dataCount = document.getElementById('data-count');
        const seriesCount = document.getElementById('series-count');
        const seriesContainer = document.getElementById('series-container');
        const addSeriesBtn = document.getElementById('add-series');
        const notification = document.getElementById('notification');
        const notificationMessage = document.getElementById('notification-message');
        const pngProgress = document.getElementById('png-progress');
        const svgProgress = document.getElementById('svg-progress');
        const downloadQuality = document.getElementById('download-quality');
        const downloadPixelRatio = document.getElementById('download-pixel-ratio');

        // 初始化事件监听
        function initEventListeners() {
            // 文件选择功能
            browseBtn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                fileInput.click();
            });

            uploadContainer.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                fileInput.click();
            });

            fileInput.addEventListener('click', (e) => {
                e.stopPropagation();
            });

            // 导入方式切换
            uploadTab.addEventListener('click', () => {
                uploadTab.classList.add('text-primary', 'border-b-2', 'border-primary', 'font-medium');
                uploadTab.classList.remove('text-gray-500');
                manualTab.classList.remove('text-primary', 'border-b-2', 'border-primary', 'font-medium');
                manualTab.classList.add('text-gray-500');
                uploadArea.classList.remove('hidden');
                manualArea.classList.add('hidden');
                hideError();
            });

            manualTab.addEventListener('click', () => {
                manualTab.classList.add('text-primary', 'border-b-2', 'border-primary', 'font-medium');
                manualTab.classList.remove('text-gray-500');
                uploadTab.classList.remove('text-primary', 'border-b-2', 'border-primary', 'font-medium');
                uploadTab.classList.add('text-gray-500');
                manualArea.classList.remove('hidden');
                uploadArea.classList.add('hidden');
                hideError();
            });

            // 文件选择处理
            fileInput.addEventListener('change', handleFileSelect);

            // 拖放功能
            uploadContainer.addEventListener('dragover', (e) => {
                e.preventDefault();
                uploadContainer.classList.add('border-primary', 'bg-blue-50');
            });

            uploadContainer.addEventListener('dragleave', () => {
                uploadContainer.classList.remove('border-primary', 'bg-blue-50');
            });

            uploadContainer.addEventListener('drop', (e) => {
                e.preventDefault();
                uploadContainer.classList.remove('border-primary', 'bg-blue-50');
                
                if (e.dataTransfer.files.length) {
                    const file = e.dataTransfer.files[0];
                    if (file.type === 'application/json' || file.name.endsWith('.json')) {
                        handleFileUpload(file);
                    } else {
                        showError('请选择JSON格式的文件');
                    }
                }
            });

            // 移除文件
            removeFile.addEventListener('click', resetFileUpload);

            // 验证手动输入的JSON
            validateJson.addEventListener('click', validateManualJson);

            // 错误详情显示/隐藏
            showErrorDetails.addEventListener('click', () => {
                errorDetails.classList.toggle('show');
                showErrorDetails.textContent = errorDetails.classList.contains('show') ? '隐藏详情' : '查看详情';
            });

            // 前往配置页面
            goToConfig.addEventListener('click', () => {
                document.getElementById('data-import').classList.add('hidden');
                chartSection.classList.remove('hidden');
                populateFieldSelects();
                // 初始生成图表
                updateChart();
            });

            // 返回数据导入页面
            backToImport.addEventListener('click', () => {
                chartSection.classList.add('hidden');
                document.getElementById('data-import').classList.remove('hidden');
                // 清除图表实例
                if (chartInstance) {
                    chartInstance.dispose();
                    chartInstance = null;
                }
            });

            // 高级配置切换
            advancedConfigToggle.addEventListener('click', () => {
                advancedConfig.classList.toggle('hidden');
                configArrow.classList.toggle('rotate-180');
            });

            // 应用更改按钮
            applyChangesBtn.addEventListener('click', updateChart);

            // 添加数据系列
            addSeriesBtn.addEventListener('click', addNewSeries);

            // 窗口大小变化时重绘图表
            window.addEventListener('resize', () => {
                if (chartInstance) {
                    chartInstance.resize();
                }
            });

            // 为动态添加的元素设置事件委托
            seriesContainer.addEventListener('click', (e) => {
                // 移除数据系列
                if (e.target.closest('.remove-series')) {
                    const seriesItem = e.target.closest('.series-item');
                    if (seriesItem) {
                        removeSeries(seriesItem);
                        scheduleChartUpdate();
                    }
                }
            });

            // 为数据系列中的独立Y轴复选框添加事件监听
            seriesContainer.addEventListener('change', (e) => {
                if (e.target.classList.contains('series-y-axis')) {
                    const yAxisConfig = e.target.closest('.series-item').querySelector('.series-y-axis-config');
                    if (e.target.checked) {
                        yAxisConfig.classList.remove('hidden');
                    } else {
                        yAxisConfig.classList.add('hidden');
                    }
                    scheduleChartUpdate();
                }
                
                // 监听其他配置变化
                if (e.target.closest('#series-container') && 
                    (e.target.classList.contains('series-field') || 
                     e.target.classList.contains('series-name') ||
                     e.target.classList.contains('series-type') ||
                     e.target.classList.contains('series-color'))) {
                    scheduleChartUpdate();
                }
            });

            // 监听系列名称输入变化
            seriesContainer.addEventListener('input', (e) => {
                if (e.target.classList.contains('series-name') || 
                    e.target.classList.contains('series-y-title')) {
                    scheduleChartUpdate();
                }
            });

            // 配置变更时自动更新图表（添加延迟防止频繁更新）
            const configElements = [
                chartType, xAxisField, chartTheme, downloadQuality, downloadPixelRatio,
                document.getElementById('chart-title'),
                document.getElementById('chart-subtitle'),
                document.getElementById('x-axis-title'),
                document.getElementById('legend-position'),
                document.getElementById('animation-type')
            ];

            configElements.forEach(element => {
                element.addEventListener('change', scheduleChartUpdate);
                if (element.tagName === 'INPUT') {
                    element.addEventListener('input', scheduleChartUpdate);
                }
            });

            // 下载按钮事件
            downloadPng.addEventListener('click', () => downloadChart('png'));
            downloadSvg.addEventListener('click', () => downloadChart('svg'));
        }

        // 显示通知
        function showNotification(message, isError = false) {
            notificationMessage.textContent = message;
            notification.className = 'notification';
            if (isError) {
                notification.classList.add('error');
            }
            notification.classList.add('show');
            
            // 3秒后隐藏通知
            setTimeout(() => {
                notification.classList.remove('show');
            }, 3000);
        }

        // 更新下载进度
        function updateDownloadProgress(type, percentage) {
            const progressBar = type === 'png' ? pngProgress : svgProgress;
            progressBar.style.width = `${percentage}%`;
            
            // 下载完成后重置进度条
            if (percentage === 100) {
                setTimeout(() => {
                    progressBar.style.width = '0%';
                }, 1000);
            }
        }

        // 添加新的数据系列
        function addNewSeries() {
            const currentSeries = seriesContainer.querySelectorAll('.series-item');
            if (currentSeries.length >= MAX_SERIES) {
                showError(`最多只能添加${MAX_SERIES}个数据系列`);
                return;
            }

            // 创建新的系列项
            const newSeriesIndex = currentSeries.length + 1;
            const newSeries = document.createElement('div');
            newSeries.className = 'series-item p-3 border border-gray-200 rounded-lg';
            
            // 设置新系列的颜色（从预设颜色列表中选取）
            const colorIndex = (newSeriesIndex - 1) % presetColors.length;
            const seriesColor = presetColors[colorIndex];
            
            newSeries.innerHTML = `
                <div class="flex justify-between items-start mb-2">
                    <label class="text-sm font-medium text-gray-700">系列 ${newSeriesIndex}</label>
                    <button type="button" class="remove-series text-gray-400 hover:text-danger">
                        <i class="fa fa-trash"></i>
                    </button>
                </div>
                <div class="grid grid-cols-1 gap-3">
                    <div>
                        <label class="block text-gray-600 mb-1 text-xs">数据字段</label>
                        <select class="series-field w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                            <!-- 动态填充字段 -->
                        </select>
                    </div>
                    <div>
                        <label class="block text-gray-600 mb-1 text-xs">系列名称</label>
                        <input type="text" class="series-name w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300" placeholder="系列名称">
                    </div>
                    <div class="grid grid-cols-2 gap-2">
                        <div>
                            <label class="block text-gray-600 mb-1 text-xs">图表类型</label>
                            <select class="series-type w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300">
                                <option value="line">折线图</option>
                                <option value="bar">柱状图</option>
                            </select>
                        </div>
                        <div>
                            <label class="block text-gray-600 mb-1 text-xs">线条/柱形颜色</label>
                            <input type="color" class="series-color w-full p-1 border border-gray-300 rounded-lg" value="${seriesColor}">
                        </div>
                    </div>
                    <div>
                        <label class="flex items-center">
                            <input type="checkbox" class="series-y-axis mr-2 h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded" checked>
                            <span class="text-xs text-gray-600">使用独立Y轴</span>
                        </label>
                    </div>
                    <div class="series-y-axis-config">
                        <label class="block text-gray-600 mb-1 text-xs">Y轴标题</label>
                        <input type="text" class="series-y-title w-full p-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-primary focus:border-primary transition-all-300" placeholder="Y轴标题">
                    </div>
                </div>
            `;
            
            // 添加到容器
            seriesContainer.appendChild(newSeries);
            
            // 更新删除按钮状态
            updateRemoveButtons();
            
            // 填充字段选项
            populateSeriesFields();
            
            // 更新系列计数
            updateSeriesCount();
            
            // 自动更新图表
            scheduleChartUpdate();
        }

        // 移除数据系列
        function removeSeries(seriesElement) {
            seriesElement.remove();
            
            // 重新编号
            const seriesItems = seriesContainer.querySelectorAll('.series-item');
            seriesItems.forEach((item, index) => {
                item.querySelector('label.text-sm').textContent = `系列 ${index + 1}`;
            });
            
            // 更新删除按钮状态
            updateRemoveButtons();
            
            // 更新系列计数
            updateSeriesCount();
        }

        // 更新删除按钮状态（至少保留一个系列）
        function updateRemoveButtons() {
            const seriesItems = seriesContainer.querySelectorAll('.series-item');
            const removeButtons = seriesContainer.querySelectorAll('.remove-series');
            
            removeButtons.forEach((btn, index) => {
                if (seriesItems.length <= 1) {
                    btn.disabled = true;
                    btn.classList.add('opacity-50', 'cursor-not-allowed');
                } else {
                    btn.disabled = false;
                    btn.classList.remove('opacity-50', 'cursor-not-allowed');
                }
            });
        }

        // 更新系列计数显示
        function updateSeriesCount() {
            const count = seriesContainer.querySelectorAll('.series-item').length;
            seriesCount.textContent = count;
        }

        // 延迟更新图表，避免频繁变更导致性能问题
        function scheduleChartUpdate() {
            // 清除之前的计时器
            if (updateTimeout) {
                clearTimeout(updateTimeout);
            }
            
            // 显示更新指示器
            applyChangesBtn.classList.add('updating');
            
            // 100ms后更新图表
            updateTimeout = setTimeout(() => {
                updateChart();
                applyChangesBtn.classList.remove('updating');
            }, 100);
        }

        // 处理文件选择
        function handleFileSelect(e) {
            if (e.target.files.length) {
                const file = e.target.files[0];
                if (file.type === 'application/json' || file.name.endsWith('.json')) {
                    handleFileUpload(file);
                } else {
                    showError('请选择JSON格式的文件');
                    fileInput.value = ''; // 重置文件输入
                }
            }
        }

        // 处理文件上传
        function handleFileUpload(file) {
            hideError();
            
            // 显示文件信息
            fileName.textContent = file.name;
            fileSize.textContent = formatFileSize(file.size);
            fileInfo.classList.remove('hidden');

            // 读取文件内容
            const reader = new FileReader();
            reader.onload = function(e) {
                try {
                    // 使用jsonlint验证JSON格式
                    const result = jsonlint.parse(e.target.result);
                    processJsonData(result);
                } catch (error) {
                    showError('JSON格式解析失败', error);
                }
            };
            
            reader.onerror = function() {
                showError('文件读取失败，请尝试其他文件');
            };
            
            reader.readAsText(file);
        }

        // 重置文件上传
        function resetFileUpload() {
            fileInput.value = '';
            fileInfo.classList.add('hidden');
            dataPreview.classList.add('hidden');
            jsonData = null;
            dataFields = [];
            hideError();
        }

        // 验证手动输入的JSON
        function validateManualJson() {
            const jsonText = jsonInput.value.trim();
            if (!jsonText) {
                showError('请输入JSON数据');
                return;
            }

            try {
                // 使用jsonlint验证JSON格式
                const result = jsonlint.parse(jsonText);
                processJsonData(result);
            } catch (error) {
                showError('JSON格式解析失败', error);
            }
        }

        // 处理JSON数据
        function processJsonData(data) {
            hideError();
            
            // 验证数据格式是否为数组
            if (!Array.isArray(data) || data.length === 0) {
                showError('不支持的JSON格式', new Error('请使用对象数组格式的JSON数据'));
                return;
            }
            
            // 验证数组中的元素是否为对象
            if (typeof data[0] !== 'object' || data[0] === null) {
                showError('不支持的JSON格式', new Error('数组元素必须是对象'));
                return;
            }
            
            jsonData = data;
            dataFields = Object.keys(data[0]);
            
            // 显示数据预览
            showDataPreview(dataFields);
            dataPreview.classList.remove('hidden');
        }

        // 显示数据预览
        function showDataPreview(columns) {
            // 清空表格
            previewHeader.innerHTML = '';
            previewBody.innerHTML = '';
            
            // 创建表头
            columns.forEach(col => {
                const th = document.createElement('th');
                th.className = 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider';
                th.textContent = col;
                previewHeader.appendChild(th);
            });
            
            // 填充表格内容（最多显示10条）
            const displayData = jsonData.slice(0, 10);
            
            displayData.forEach((item, index) => {
                const tr = document.createElement('tr');
                tr.className = index % 2 === 0 ? 'bg-white' : 'bg-gray-50';
                
                columns.forEach(col => {
                    const td = document.createElement('td');
                    td.className = 'px-6 py-4 whitespace-nowrap text-sm text-gray-900';
                    td.textContent = item[col] !== undefined ? item[col] : '';
                    tr.appendChild(td);
                });
                
                previewBody.appendChild(tr);
            });
        }

        // 填充字段选择下拉框
        function populateFieldSelects() {
            // 清空现有选项
            xAxisField.innerHTML = '';
            
            // 填充X轴字段选项
            dataFields.forEach(field => {
                const option = document.createElement('option');
                option.value = field;
                option.textContent = field;
                xAxisField.appendChild(option);
            });
            
            // 填充系列字段选项
            populateSeriesFields();
            
            // 重置最后配置
            lastConfig = {};
        }

        // 填充数据系列的字段选择下拉框
        function populateSeriesFields() {
            const seriesFields = seriesContainer.querySelectorAll('.series-field');
            
            seriesFields.forEach(select => {
                // 保存当前选中的值
                const currentValue = select.value;
                
                // 清空现有选项
                select.innerHTML = '';
                
                // 填充选项
                dataFields.forEach(field => {
                    const option = document.createElement('option');
                    option.value = field;
                    option.textContent = field;
                    select.appendChild(option);
                });
                
                // 尝试恢复之前的选择
                if (currentValue && dataFields.includes(currentValue)) {
                    select.value = currentValue;
                } else if (dataFields.length > 0) {
                    // 如果没有选中值或选中值不存在，则选择第一个选项
                    select.value = dataFields[0];
                    
                    // 如果系列名称为空，则自动填充为字段名
                    const seriesItem = select.closest('.series-item');
                    const seriesNameInput = seriesItem.querySelector('.series-name');
                    if (!seriesNameInput.value) {
                        seriesNameInput.value = dataFields[0];
                    }
                    
                    // 如果Y轴标题为空，则自动填充为字段名
                    const yTitleInput = seriesItem.querySelector('.series-y-title');
                    if (!yTitleInput.value) {
                        yTitleInput.value = dataFields[0];
                    }
                }
            });
        }

        // 获取当前配置
        function getCurrentConfig() {
            // 收集所有数据系列的配置
            const seriesConfig = [];
            const seriesItems = seriesContainer.querySelectorAll('.series-item');
            
            seriesItems.forEach((item, index) => {
                const field = item.querySelector('.series-field').value;
                const name = item.querySelector('.series-name').value || field;
                const type = item.querySelector('.series-type').value;
                const color = item.querySelector('.series-color').value;
                const useYAxis = item.querySelector('.series-y-axis').checked;
                const yTitle = item.querySelector('.series-y-title').value || name;
                
                seriesConfig.push({
                    field,
                    name,
                    type,
                    color,
                    useYAxis,
                    yTitle,
                    axisIndex: useYAxis ? index : 0 // 独立Y轴使用索引，共享Y轴使用0
                });
            });
            
            return {
                type: chartType.value,
                xField: xAxisField.value,
                theme: chartTheme.value,
                title: document.getElementById('chart-title').value,
                subtitle: document.getElementById('chart-subtitle').value,
                xTitle: document.getElementById('x-axis-title').value,
                legendPosition: document.getElementById('legend-position').value,
                animationType: document.getElementById('animation-type').value,
                downloadQuality: parseFloat(downloadQuality.value),
                downloadPixelRatio: parseInt(downloadPixelRatio.value),
                series: seriesConfig
            };
        }

        // 检查配置是否有变化
        function hasConfigChanged(newConfig) {
            if (Object.keys(lastConfig).length === 0) return true;
            
            // 简单比较字符串化的配置
            return JSON.stringify(newConfig) !== JSON.stringify(lastConfig);
        }

        // 更新图表（核心优化部分）
        function updateChart() {
            const config = getCurrentConfig();
            
            // 检查配置是否有变化，没有变化则不更新
            if (!hasConfigChanged(config)) {
                return;
            }
            
            // 保存当前配置
            lastConfig = JSON.parse(JSON.stringify(config));
            
            // 验证选择
            if (!config.xField) {
                showError('请选择X轴/类别字段');
                return;
            }
            
            if (config.series.length === 0) {
                showError('请至少添加一个数据系列');
                return;
            }
            
            // 验证所有系列都选择了字段
            for (let i = 0; i < config.series.length; i++) {
                if (!config.series[i].field) {
                    showError(`请为系列 ${i+1} 选择数据字段`);
                    return;
                }
            }
            
            // 准备图表数据
            const xData = jsonData.map(item => item[config.xField]);
            
            // 为每个系列准备数据
            const seriesData = config.series.map(series => {
                return jsonData.map(item => item[series.field]);
            });
            
            // 更新数据计数
            dataCount.textContent = xData.length;
            
            // 如果图表实例不存在，创建新实例
            if (!chartInstance) {
                chartInstance = echarts.init(echartsContainer, config.theme);
            } else {
                // 如果主题变化，需要重新初始化图表
                if (chartInstance.getOption().theme !== config.theme) {
                    chartInstance.dispose();
                    chartInstance = echarts.init(echartsContainer, config.theme);
                }
            }
            
            // 收集所有需要独立Y轴的系列
            const yAxes = [{
                type: 'value',
                name: config.series[0].useYAxis ? config.series[0].yTitle : '',
                position: 'left',
                axisLine: {
                    lineStyle: {
                        color: config.series[0].color
                    }
                },
                nameTextStyle: {
                    color: config.series[0].color
                }
            }];
            
            // 添加额外的Y轴
            for (let i = 1; i < config.series.length; i++) {
                if (config.series[i].useYAxis) {
                    yAxes.push({
                        type: 'value',
                        name: config.series[i].yTitle,
                        position: i % 2 === 0 ? 'left' : 'right', // 左右交替放置
                        offset: i > 1 ? (i - 1) * 60 : 0, // 偏移避免重叠
                        axisLine: {
                            lineStyle: {
                                color: config.series[i].color
                            }
                        },
                        nameTextStyle: {
                            color: config.series[i].color
                        }
                    });
                }
            }
            
            // 基础配置
            const option = {
                title: {
                    text: config.title || '数据可视化图表',
                    subtext: config.subtitle || '',
                    left: 'center'
                },
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'cross'
                    }
                },
                legend: {
                    data: config.series.map(s => s.name),
                    top: config.legendPosition === 'top' ? 'top' : undefined,
                    right: config.legendPosition === 'right' ? 'right' : undefined,
                    bottom: config.legendPosition === 'bottom' ? 'bottom' : undefined,
                    left: config.legendPosition === 'left' ? 'left' : undefined,
                    show: config.legendPosition !== 'none'
                },
                grid: {
                    left: '8%',
                    right: '8%',
                    bottom: '10%',
                    containLabel: true
                },
                xAxis: {
                    type: 'category',
                    boundaryGap: config.type === 'line',
                    name: config.xTitle || config.xField,
                    data: xData
                },
                yAxis: yAxes,
                animation: config.animationType !== 'none',
                animationDuration: config.animationType === 'slow' ? 2000 : 
                                 (config.animationType === 'fast' ? 500 : 1000),
                series: []
            };
            
            // 配置系列数据
            config.series.forEach((series, index) => {
                option.series.push({
                    name: series.name,
                    type: series.type,
                    data: seriesData[index],
                    smooth: series.type === 'line', // 折线图平滑曲线
                    itemStyle: {
                        color: series.color
                    },
                    lineStyle: {
                        color: series.color
                    },
                    yAxisIndex: series.axisIndex, // 指定使用哪个Y轴
                    emphasis: {
                        focus: 'series'
                    }
                });
            });
            
            // 特殊处理雷达图
            if (config.type === 'radar') {
                // 雷达图使用极坐标而非X/Y轴
                delete option.xAxis;
                delete option.yAxis;
                
                // 准备雷达图指示器
                const maxValues = {};
                
                // 计算每个维度的最大值
                xData.forEach((indicator, i) => {
                    maxValues[indicator] = Math.max(...seriesData.map(series => series[i])) * 1.2;
                });
                
                option.radar = {
                    indicator: xData.map(indicator => ({
                        name: indicator,
                        max: maxValues[indicator]
                    }))
                };
                
                // 调整系列配置适应雷达图
                option.series.forEach((series, index) => {
                    series.type = 'radar';
                    series.data = [{
                        value: seriesData[index],
                        name: series.name,
                        itemStyle: {
                            color: config.series[index].color
                        },
                        lineStyle: {
                            color: config.series[index].color
                        }
                    }];
                });
            }
            
            // 使用setOption更新图表，ECharts会智能更新变化的部分
            chartInstance.setOption(option, true);
        }

        // 下载图表
        function downloadChart(type) {
            if (!chartInstance) {
                showNotification('请先生成图表', true);
                return;
            }
            
            // 获取当前下载配置
            const quality = parseFloat(downloadQuality.value);
            const pixelRatio = parseInt(downloadPixelRatio.value);
            
            // 显示加载状态
            const downloadBtn = type === 'png' ? downloadPng : downloadSvg;
            const originalText = downloadBtn.innerHTML;
            downloadBtn.innerHTML = `<span class="spinner"></span>正在生成...`;
            downloadBtn.disabled = true;
            
            // 更新进度
            updateDownloadProgress(type, 30);
            
            try {
                if (type === 'png') {
                    // 生成PNG图片
                    const dataURL = chartInstance.getDataURL({
                        type: 'png',
                        pixelRatio: pixelRatio,
                        quality: quality,
                        excludeComponents: ['toolbox']
                    });
                    
                    // 创建下载链接
                    const link = document.createElement('a');
                    const now = new Date();
                    const timestamp = `${now.getFullYear()}${(now.getMonth()+1).toString().padStart(2,'0')}${now.getDate().toString().padStart(2,'0')}${now.getHours().toString().padStart(2,'0')}${now.getMinutes().toString().padStart(2,'0')}`;
                    
                    link.download = `chart-${timestamp}.png`;
                    link.href = dataURL;
                    
                    // 模拟进度
                    setTimeout(() => {
                        updateDownloadProgress(type, 80);
                        
                        // 触发下载
                        setTimeout(() => {
                            link.click();
                            updateDownloadProgress(type, 100);
                            showNotification('PNG图片下载成功');
                            
                            // 恢复按钮状态
                            downloadBtn.innerHTML = originalText;
                            downloadBtn.disabled = false;
                        }, 300);
                    }, 500);
                    
                } else {
                    // 生成SVG图片
                    updateDownloadProgress(type, 50);
                    
                    // 延迟模拟生成过程
                    setTimeout(() => {
                        const svg = chartInstance.getOption().svg;
                        const dataURL = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svg)));
                        
                        // 创建下载链接
                        const link = document.createElement('a');
                        const now = new Date();
                        const timestamp = `${now.getFullYear()}${(now.getMonth()+1).toString().padStart(2,'0')}${now.getDate().toString().padStart(2,'0')}${now.getHours().toString().padStart(2,'0')}${now.getMinutes().toString().padStart(2,'0')}`;
                        
                        link.download = `chart-${timestamp}.svg`;
                        link.href = dataURL;
                        
                        // 模拟进度
                        updateDownloadProgress(type, 80);
                        
                        // 触发下载
                        setTimeout(() => {
                            link.click();
                            updateDownloadProgress(type, 100);
                            showNotification('SVG图片下载成功');
                            
                            // 恢复按钮状态
                            downloadBtn.innerHTML = originalText;
                            downloadBtn.disabled = false;
                        }, 300);
                    }, 600);
                }
            } catch (error) {
                console.error('下载失败:', error);
                showNotification('下载失败，请重试', true);
                
                // 恢复按钮状态
                downloadBtn.innerHTML = originalText;
                downloadBtn.disabled = false;
                updateDownloadProgress(type, 0);
            }
        }

        // 显示错误信息
        function showError(message, error) {
            jsonError.classList.remove('hidden');
            errorMessage.textContent = message;
            
            if (error) {
                errorStack.textContent = `错误信息: ${error.message}\n\n位置: ${error.at ? `行: ${error.at.line}, 列: ${error.at.column}` : '未知'}`;
            } else {
                errorStack.textContent = '';
            }
            
            // 收起错误详情
            errorDetails.classList.remove('show');
            showErrorDetails.textContent = '查看详情';
        }

        // 隐藏错误信息
        function hideError() {
            jsonError.classList.add('hidden');
        }

        // 格式化文件大小
        function formatFileSize(bytes) {
            if (bytes < 1024) return bytes + ' B';
            else if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
            else return (bytes / 1048576).toFixed(1) + ' MB';
        }

        // 初始化应用
        function initApp() {
            initEventListeners();
        }

        // 页面加载完成后初始化
        window.addEventListener('load', initApp);
    </script>
</body>
</html>
    